import { fabric } from "fabric";
export default {
  data() {
    return {
      //fabric画板相关
      canvas: null,
      //图形对象
      graph: null,
      // 鼠标按下的坐标
      downPoint: null,
      drawTarget: null,
      drawFlag: false,
    };
  },
  mounted() {},
  methods: {
    //初始化Fabric
    initFabric() {
      this.canvas = new fabric.Canvas("fabricCanvasContainer", {
        backgroundColor: "transparent",
      });
      this.setCanvasSize();
      // 鼠标在画布上按下
      this.canvas.on("mouse:down", this.canvasMouseDown);
      // 鼠标在画布上放开
      this.canvas.on("mouse:up", this.canvasMouseUp);
      // 鼠标在画布上移动
      this.canvas.on("mouse:move", this.canvasMouseMove);
      //监听路劲创建完成
      this.canvas.on("path:created", (e) => {
        this.graph = e.path;
      });
      //监听文本框创建完成
      this.canvas.on("object:added", (e) => {
        let addedObject = e.target;
        if (addedObject instanceof fabric.IText) {
          //删除无效的文本框
          let allGraphArr = this.getAllGraph();
          allGraphArr.forEach((v, i) => {
            let { type, text } = v;
            if (
              type == "i-text" &&
              text.trim() == "" &&
              i < allGraphArr.length - 1
            ) {
              this.removeGraph(v);
            }
          });
        }
      });
      this.canvas.selectionColor = "transparent";
      this.canvas.selectionBorderColor = "transparent";
    },

    //鼠标在画布上按下
    canvasMouseDown(e) {
      this.drawFlag = true;
      this.drawTarget = e.target;
      this.downPoint = e.absolutePointer;
      this.draw(e);
    },

    //鼠标在画布上移动
    canvasMouseMove(e) {
      let {
        downPoint,
        drawFlag,
        drawTarget,
        fabricDrawerType,
        graph,
        canvas,
      } = this;

      if (!downPoint || !drawFlag || drawTarget) {
        return;
      }
      if (graph && canvas) {
        let { absolutePointer } = e;
        let top = Math.min(downPoint.y, absolutePointer.y);
        let left = Math.min(downPoint.x, absolutePointer.x);
        let width = Math.abs(downPoint.x - absolutePointer.x);
        let height = Math.abs(downPoint.y - absolutePointer.y);
        switch (fabricDrawerType) {
          //云
          case "cloud":
            this.canvas.remove(this.graph);
            let X1 = downPoint.x;
            let Y1 = downPoint.y;
            let X2 = absolutePointer.x;
            let Y2 = absolutePointer.y;
            let n = 60;
            let rx = Math.abs(X2 - X1);
            let ry = Math.abs(Y2 - Y1);
            let lRx = Math.floor(rx * 1.2);
            let lRy = Math.floor(ry * 1.2);
            let centerX1 = (X2 - X1) / 2 + X1;
            let centerY1 = (Y2 - Y1) / 2 + Y1;
            let pathData = "";
            for (let angle = 0; angle <= 360; angle += 360 / n) {
              let t = Math.tan((angle / 360) * Math.PI);
              let px = (rx * (1 - t ** 2)) / (1 + t ** 2) + centerX1;
              let py = (ry * 2 * t) / (1 + t ** 2) + centerY1;
              if (angle === 0) {
                pathData += `M ${px} ${py}`;
              } else if ((angle / (360 / n)) % 2 === 1) {
                let lpx = (lRx * (1 - t ** 2)) / (1 + t ** 2) + centerX1;
                let lpy = (lRy * 2 * t) / (1 + t ** 2) + centerY1;
                pathData += ` Q ${lpx} ${lpy}`;
              } else {
                pathData += `,  ${px} ${py}`;
              }
            }
            this.graph = new fabric.Path(pathData, {
              stroke:
                this.colorBarSource?.[
                  this.annotationsDrawer?.colorActive ?? 0
                ] ?? "red",
              strokeWidth: this.annotationsDrawer.sliderValue,
              fill: "transparent",
              centeredRotation: true,
            });
            this.canvas.add(this.graph);
            break;

          //矩形
          case "rect":
            this.graph.set({ top, left, width, height });
            break;

          //椭圆
          case "ellipse":
            this.graph.set({ top, left, rx: width / 2, ry: height / 2 });
            break;

          //箭头
          case "arrow":
            this.canvas.remove(this.graph);
            let x1 = downPoint.x;
            let y1 = downPoint.y;
            let x2 = absolutePointer.x;
            let y2 = absolutePointer.y;
            let w = x2 - x1;
            let h = y2 - y1;
            let sh = Math.cos(Math.PI / 4) * 16;
            let sin = h / Math.sqrt(Math.pow(w, 2) + Math.pow(h, 2));
            let cos = w / Math.sqrt(Math.pow(w, 2) + Math.pow(h, 2));
            let w1 = (16 * sin) / 4;
            let h1 = (16 * cos) / 4;
            let centerX = sh * cos;
            let centerY = sh * sin;

            let path = " M " + x1 + " " + y1;
            path += " L " + (x2 - centerX + w1) + " " + (y2 - centerY - h1);
            path +=
              " L " + (x2 - centerX + w1 * 2) + " " + (y2 - centerY - h1 * 2);
            path += " L " + x2 + " " + y2;
            path +=
              " L " + (x2 - centerX - w1 * 2) + " " + (y2 - centerY + h1 * 2);
            path += " L " + (x2 - centerX - w1) + " " + (y2 - centerY + h1);
            path += " Z";
            this.graph = new fabric.Path(path, {
              fill:
                this.colorBarSource?.[
                  this.annotationsDrawer?.colorActive ?? 0
                ] ?? "red",
              stroke:
                this.colorBarSource?.[
                  this.annotationsDrawer?.colorActive ?? 0
                ] ?? "red",
              strokeWidth: this.annotationsDrawer.sliderValue,
            });
            this.canvas.add(this.graph);
            break;

          default:
            break;
        }
        this.canvas.requestRenderAll();
      }
    },

    //鼠标在画布上放开
    canvasMouseUp(e) {
      let { fabricDrawerType } = this;
      let { width, height } = this.graph ?? {};
      switch (fabricDrawerType) {
        //自由绘制
        case "all":
          if (width < 10) {
            this.removeGraph(this.graph);
            this.graph = null;
          }
          break;

        //矩形
        case "rect":
          if (width < 10 || height < 10) {
            this.removeGraph(this.graph);
            this.graph = null;
          }
          break;

        //云
        case "cloud":
          if (width < 10 || height < 10) {
            this.removeGraph(this.graph);
            this.graph = null;
          }
          break;

        //椭圆
        case "ellipse":
          if (width < 10 || height < 10) {
            this.removeGraph(this.graph);
            this.graph = null;
          }
          break;

        //剪头
        case "arrow":
          if (width < 15) {
            this.removeGraph(this.graph);
            this.graph = null;
          }
          break;

        default:
          break;
      }
      this.drawFlag = false;
      this.drawTarget = null;
    },

    //绘制
    draw(e) {
      let { fabricDrawerType } = this;
      switch (fabricDrawerType) {
        //云
        case "cloud":
          this.createCloud(e);
          break;

        //任意形状
        case "all":
          break;

        //矩形
        case "rect":
          this.createRect(e);
          break;

        //椭圆
        case "ellipse":
          this.createEllipse(e);
          break;

        //箭头
        case "arrow":
          this.createArrow(e);
          break;

        //文本
        case "text":
          this.createText(e);
          break;

        default:
          break;
      }
      // 将矩形添加到画布上
      if (this.canvas && this.graph) {
        let { type, width, height } = this.graph;
        this.canvas && this.canvas.add(this.graph);
        //文本
        if (fabricDrawerType == "text") {
          this.graph.enterEditing();
          this.graph.hiddenTextarea?.focus();
        }
      }
    },

    //创建矩形
    createRect(e) {
      let { absolutePointer } = e;
      let { downPoint } = this;
      let top = Math.min(downPoint.y, absolutePointer.y);
      let left = Math.min(downPoint.x, absolutePointer.x);
      let width = Math.abs(downPoint.x - absolutePointer.x);
      let height = Math.abs(downPoint.y - absolutePointer.y);
      this.graph = new fabric.Rect({
        top,
        left,
        width,
        height,
        fill: "transparent",
        strokeWidth: this.annotationsDrawer.sliderValue,
        stroke:
          this.colorBarSource?.[this.annotationsDrawer?.colorActive ?? 0] ??
          "red",
      });
      this.graph.fabricDrawerType = this.fabricDrawerType;
    },

    //创建椭圆
    createEllipse(e) {
      let { absolutePointer } = e;
      let { downPoint } = this;
      let rx = Math.abs(downPoint.x - absolutePointer.x) / 2;
      let ry = Math.abs(downPoint.y - absolutePointer.y) / 2;
      let top =
        absolutePointer.y > downPoint.y ? downPoint.y : downPoint.y - ry * 2;
      let left =
        absolutePointer.x > downPoint.x ? downPoint.x : downPoint.x - rx * 2;
      this.graph = new fabric.Ellipse({
        top,
        left,
        rx,
        ry,
        fill: "transparent",
        stroke:
          this.colorBarSource?.[this.annotationsDrawer?.colorActive ?? 0] ??
          "red",
        strokeWidth: this.annotationsDrawer.sliderValue,
      });
      this.graph.fabricDrawerType = this.fabricDrawerType;
    },

    //创建箭头
    createArrow(e) {
      let { absolutePointer } = e;
      let { downPoint } = this;
      let x1 = downPoint.x;
      let y1 = downPoint.y;
      let x2 = absolutePointer.x;
      let y2 = absolutePointer.y;
      let w = x2 - x1;
      let h = y2 - y1;
      let sh = Math.cos(Math.PI / 4) * 16;
      let sin = h / Math.sqrt(Math.pow(w, 2) + Math.pow(h, 2));
      let cos = w / Math.sqrt(Math.pow(w, 2) + Math.pow(h, 2));
      let w1 = (16 * sin) / 4;
      let h1 = (16 * cos) / 4;
      let centerX = sh * cos;
      let centerY = sh * sin;
      let path = " M " + x1 + " " + y1;
      path += " L " + (x2 - centerX + w1) + " " + (y2 - centerY - h1);
      path += " L " + (x2 - centerX + w1 * 2) + " " + (y2 - centerY - h1 * 2);
      path += " L " + x2 + " " + y2;
      path += " L " + (x2 - centerX - w1 * 2) + " " + (y2 - centerY + h1 * 2);
      path += " L " + (x2 - centerX - w1) + " " + (y2 - centerY + h1);
      path += " Z";
      // 创建路径对象
      this.graph = new fabric.Path(path, {
        fill:
          this.colorBarSource?.[this.annotationsDrawer?.colorActive ?? 0] ??
          "red",
        stroke:
          this.colorBarSource?.[this.annotationsDrawer?.colorActive ?? 0] ??
          "red",
        strokeWidth: this.annotationsDrawer.sliderValue,
      });
      this.graph.fabricDrawerType = this.fabricDrawerType;
    },

    //创建可编辑文本
    createText(e) {
      let { absolutePointer } = e;
      this.graph = new fabric.IText("", {
        left: absolutePointer.x,
        top: absolutePointer.y - 10,
        fontSize: 18,
        borderColor:
          this.colorBarSource?.[this.annotationsDrawer?.colorActive ?? 0] ??
          "red",
        fill:
          this.colorBarSource?.[this.annotationsDrawer?.colorActive ?? 0] ??
          "red",
        hasControls: false,
        centeredRotation: true,
      });
      this.graph.fabricDrawerType = this.fabricDrawerType;
    },

    //创建云
    createCloud(e) {
      let { absolutePointer } = e;
      let { downPoint } = this;
      let x1 = downPoint.x;
      let y1 = downPoint.y;
      let x2 = absolutePointer.x;
      let y2 = absolutePointer.y;
      let n = 60;
      let rx = Math.abs(x2 - x1);
      let ry = Math.abs(y2 - y1);
      let lRx = Math.floor(rx * 1.2);
      let lRy = Math.floor(ry * 1.2);
      let centerX = (x2 - x1) / 2 + x1;
      let centerY = (y2 - y1) / 2 + y1;
      let path = "";
      for (let angle = 0; angle <= 360; angle += 360 / n) {
        let t = Math.tan((angle / 360) * Math.PI);

        let px = (rx * (1 - t ** 2)) / (1 + t ** 2) + centerX;
        let py = (ry * 2 * t) / (1 + t ** 2) + centerY;

        if (angle === 0) {
          path += `M ${px} ${py}`;
        } else if ((angle / (360 / n)) % 2 === 1) {
          let lpx = (lRx * (1 - t ** 2)) / (1 + t ** 2) + centerX;
          let lpy = (lRy * 2 * t) / (1 + t ** 2) + centerY;
          path += ` Q ${lpx} ${lpy}`;
        } else {
          path += `,  ${px} ${py}`;
        }
      }

      this.graph = new fabric.Path(path, {
        stroke:
          this.colorBarSource?.[this.annotationsDrawer?.colorActive ?? 0] ??
          "red",
        strokeWidth: this.annotationsDrawer.sliderValue,
        fill: "transparent",
        centeredRotation: true,
        fabricDrawerType: "xxxx",
      });
      this.graph.fabricDrawerType = this.fabricDrawerType;
    },

    //获取图形实例
    getObjectsByType(type = "") {
      return this.canvas.getObjects().filter(function(obj) {
        return obj.type === type;
      });
    },

    //删除图形对象
    removeGraph(obj = {}) {
      this.canvas && this.canvas.remove(obj);
    },

    //获取所有图形实例
    getAllGraph() {
      return this.canvas?.getObjects();
    },

    //设置画布尺寸
    setCanvasSize() {
      let pageRef = this.$refs["pageBimVisual-container"];
      if (this.canvas && pageRef) {
        this.canvas.setWidth(pageRef?.clientWidth);
        this.canvas.setHeight(pageRef?.clientHeight);
      }
    },

    //撤回
    fabricRevocation() {
      this.downPoint = {};
      //获取所有图形实例
      let graphArr = this.getAllGraph();
      //获取所有的文本
      let textArr = this.getObjectsByType("i-text");
      //删除所有无效的文本框
      textArr.forEach((v) => {
        let { text } = v;
        if (text.trim() == "") {
          this.removeGraph(v);
        }
      });
      //有效的图形数组
      let validData = [];
      graphArr.filter((v) => {
        let { type, text } = v;
        if ((type == "i-text" && text.trim() != "") || type != "i-text") {
          validData.push(v);
        }
      });
      this.removeGraph(validData.pop());
    },

    //生成图片
    getFabricImg() {
      if (!this.canvas) {
        return "";
      }
      var imageData = this.canvas.toDataURL({
        format: "png", // 保存格式为png
        quality: 1, // 图片质量为1（最高质量）
      });
      return imageData;
    },

    //取消图形选中
    discardActiveObject() {
      if (this.canvas) {
        this.canvas.discardActiveObject();
        this.canvas.requestRenderAll();
      }
    },

    //销毁
    disposeFabric() {
      if (this.canvas) {
        this.canvas.clear();
        this.canvas.dispose();
        this.canvas = null;
        this.graph = null;
        this.downPoint = null;
        this.drawTarget = null;
        this.drawFlag = false;
        this.fabricDrawerType = "";
        this.topToolBarActiveIndex = null;
        this.fabricBarActiveIndex = null;
        this.fabricDrawerType = "";
      }
    },
  },
};
